import { _decorator, Component, instantiate, Node, NodePool, Tween, tween, UIOpacity, UITransform, v3, Vec3 } from 'cc';
import { $planet_EFloat_poof$, type $planet_FloatIns_poof$, $planet_GetFloatComponent_poof$, $planet_GetFloatPrefab_poof$ } from '../float/config.float';
import $planet_GameAssets_poof$ from '../manager/game-assets';
const { ccclass, property } = _decorator;

@ccclass('$planet_Float_poof$')
export class $planet_Float_poof$ extends Component {
	private static $planet__ins_poof$: $planet_Float_poof$;
	/** 全局唯一安全实例 */
	public static get $planet_ins_poof$(){
		return $planet_Float_poof$.$planet__ins_poof$;
	}

	@property(UITransform)
	private ui_pointer: UITransform = null;
	@property(Node)
	private $planet_node_resetting_poof$: Node = null;

	private $planet_ui_resetting_poof$: UITransform;
	private $planet_op_resetting_poof$: UIOpacity;

	protected onLoad(): void {
		$planet_Float_poof$.$planet__ins_poof$ = this;
		this.ui_pointer.node.active = false;
		this.$planet_node_resetting_poof$.active = false;
		this.$planet_ui_resetting_poof$ = this.$planet_node_resetting_poof$.getComponent(UITransform);
		this.$planet_op_resetting_poof$ = this.$planet_node_resetting_poof$.getComponent(UIOpacity);
		abd.$planet_cc_poof$.$planet_skinPeeler_poof$(this.$planet_node_resetting_poof$, $planet_GameAssets_poof$.$planet_getLangTexture_poof$(6), {width: true});
	}

	private static $planet_float_pool_poof$: Map<any, NodePool> = new Map();

	private static async $planet_getFloat_poof$<F extends $planet_EFloat_poof$>(f: F): Promise<$planet_FloatIns_poof$<F>>{
		let pool = $planet_Float_poof$.$planet_float_pool_poof$.get(f);
		if(!pool){
			pool = new NodePool();
			$planet_Float_poof$.$planet_float_pool_poof$.set(f, pool);
		}

		let node: Node;
		if(pool.size() > 0) node = pool.get();
		else{
			node = instantiate(await $planet_GetFloatPrefab_poof$(f));
		}

		//@ts-ignore
		return node.getComponent(await $planet_GetFloatComponent_poof$(f));
	}

	public static $planet_recycleFlot_poof$(sign: any, node: Node){
		let pool = $planet_Float_poof$.$planet_float_pool_poof$.get(sign);
		if(!pool){
			pool = new NodePool();
			$planet_Float_poof$.$planet_float_pool_poof$.set(sign, pool);
		}

		pool.put(node);
	}

	private static $planet_hilight_token_poof$: Map<string, {depth: number[], node: Node, parent: Node}[]> = new Map();

	public static $planet_heightLight_poof$(list: Node[]){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		let canvas = abd.$planet_cc_poof$.$planet_canvas_poof$;
		let base = this.$planet_ins_poof$.node.children.length;

		let info = list.filter(n=>n && n.isValid).map(node=>{
			let depth: number[] = [];
			let r = node;
			while(r!=canvas.node){
				depth.unshift(r.getSiblingIndex());
				r = r.parent;
			}
			return {depth, node, parent: node.parent};
		}).sort((a, b)=>{
			let i = 0;
			while(a.depth[i]==b.depth[i]) i++;
			return a.depth[i] - b.depth[i];
		});

		info.forEach((el, i)=>{
			el.node.setParent($planet_Float_poof$.$planet_ins_poof$.node, true);
			el.node.setSiblingIndex(base + i);
		});

		let token = abd.$planet_string_poof$.$planet_randomToken_poof$(5, 36, t=>!$planet_Float_poof$.$planet_hilight_token_poof$.has(t));

		$planet_Float_poof$.$planet_hilight_token_poof$.set(token, info);

		return token;
	}

	public static $planet_releaseHILIT_poof$(token: string){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		if(!this.$planet_hilight_token_poof$.has(token)) return void 0;

		let info = this.$planet_hilight_token_poof$.get(token);
		this.$planet_hilight_token_poof$.delete(token);

		info.forEach(el=>{
			el.node.setParent(el.parent, true);
			el.node.setSiblingIndex(el.depth.pop());
		});
	}

	private static $planet_pool_map_poof$: Map<Node, NodePool> = new Map();
	public static $planet_Reap_poof$(node: Node, count: number, world_position: Vec3){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		let target_position = abd.$planet_cc_poof$.$planet_getLocalPosition_poof$($planet_Float_poof$.$planet_ins_poof$.node, node);
		let origin_position = abd.$planet_cc_poof$.$planet_getLocalPosition_poof$($planet_Float_poof$.$planet_ins_poof$.node, world_position);

		let pool = this.$planet_pool_map_poof$.get(node);
		if(!pool){
			pool = new NodePool();
			this.$planet_pool_map_poof$.set(node, pool);
		}

		count = count ?? abd.$planet_number_poof$.$planet_random_poof$(3, 5, 0);
		let range_half = 200;
		let np = new abd.$planet_NudityPromise_poof$<0>();
		for(let i = 0; i<count; i++){
			let item: Node
			if(pool.size() > 0) item = pool.get();
			else item = instantiate(node);

			item.setScale(0.3, 0.3, 1);
			item.setPosition(origin_position);
			item.setParent($planet_Float_poof$.$planet_ins_poof$.node);

			tween(item)
			.to(0.2, {position: v3(item.position.x + abd.$planet_number_poof$.$planet_random_poof$(-range_half, range_half, 2), item.position.y + abd.$planet_number_poof$.$planet_random_poof$(-range_half, range_half, 2), item.position.z), scale: v3(1.2, 1.2, 1)}, {easing: 'cubicOut'})
			.delay(0.3)
			.to(0.5, {position: target_position, scale: v3(1, 1, 1)}, {easing: 'cubicOut'})
			.to(0.05, {scale: v3(1.1, 1.1, 1)})
			.to(0.05, {scale: v3(1, 1, 1)})
			.call(()=>{
				pool.put(item);
				if(i==count-1) np.$planet_resolve_poof$(0);
			}).start();
		}
		return np.$planet_promise_poof$;
	}

	public static async $planet_Hint_poof$(str: string){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		let comp = await this.$planet_getFloat_poof$($planet_EFloat_poof$.$planet_HINT_poof$);
		comp.node.setParent($planet_Float_poof$.$planet_ins_poof$.node);

		$planet_Float_poof$.$planet_recycleFlot_poof$($planet_EFloat_poof$.$planet_HINT_poof$, await comp.$planet_show_poof$(str));
	}

	public static async $planet_Good_poof$(hit: number){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		let comp = await this.$planet_getFloat_poof$($planet_EFloat_poof$.$planet_GOOD_poof$);
		comp.node.setParent($planet_Float_poof$.$planet_ins_poof$.node);

		$planet_Float_poof$.$planet_recycleFlot_poof$($planet_EFloat_poof$.$planet_GOOD_poof$, await comp.$planet_show_poof$(hit));
	}

	public static async $planet_Congratulation_poof$(symbol: number, desc: string){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		let comp = await this.$planet_getFloat_poof$($planet_EFloat_poof$.$planet_CONGRATULATION_poof$);
		comp.node.setParent($planet_Float_poof$.$planet_ins_poof$.node);

		$planet_Float_poof$.$planet_recycleFlot_poof$($planet_EFloat_poof$.$planet_CONGRATULATION_poof$, await comp.$planet_show_poof$(symbol, desc));
	}

	private static $planet_cache_elsb_poof$: Node;
	private static $planet_elsp_position_poof$ = v3(0, 0, 0);
	public static $planet_setElsb_poof$(node: Node){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		abd.$planet_cc_poof$.$planet_getLocalPosition_poof$($planet_Float_poof$.$planet_ins_poof$.node, node, $planet_Float_poof$.$planet_elsp_position_poof$);
		node.removeFromParent();
		node.setParent($planet_Float_poof$.$planet_ins_poof$.node);
		node.setPosition($planet_Float_poof$.$planet_elsp_position_poof$);
		$planet_Float_poof$.$planet_cache_elsb_poof$ = node;
	}

	public static $planet_moveElsb_poof$(target: Node, duration?: number){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		if(!$planet_Float_poof$.$planet_cache_elsb_poof$) return Promise.resolve(0);

		let [UI, ui] = [$planet_Float_poof$.$planet_cache_elsb_poof$, target].map(n=>n.getComponent(UITransform));

		let [A, a] = [UI, ui].map(_=>_.width * _.node.scale.x * _.height * _.node.scale.y);
		let [sw, sh] = [ui.width * ui.node.scale.x / UI.width, ui.height * ui.node.scale.y / UI.height];
		let scale = a > A ? Math.max(sw, sh) : Math.min(sw, sh);

		duration = duration ?? 0.5;
		abd.$planet_cc_poof$.$planet_getLocalPosition_poof$($planet_Float_poof$.$planet_ins_poof$.node, target, $planet_Float_poof$.$planet_elsp_position_poof$);

		let np = new abd.$planet_NudityPromise_poof$<0>();
		Tween.stopAllByTarget($planet_Float_poof$.$planet_cache_elsb_poof$);
		tween($planet_Float_poof$.$planet_cache_elsb_poof$)
		.to(duration, {position: $planet_Float_poof$.$planet_elsp_position_poof$, scale: v3(scale, scale, 1)}, {easing: 'quartInOut'})
		.call(()=>np.$planet_resolve_poof$(0))
		.start();

		return np.$planet_promise_poof$;
	}

	public static $planet_destroyElsb_poof$(){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		if($planet_Float_poof$.$planet_cache_elsb_poof$){
			$planet_Float_poof$.$planet_cache_elsb_poof$.removeFromParent();
			$planet_Float_poof$.$planet_cache_elsb_poof$.destroy();
			$planet_Float_poof$.$planet_cache_elsb_poof$ = null;
		}
	}

	public static $planet_pointerTo_poof$(node: Node){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		$planet_Float_poof$.$planet_hidePointer_poof$();
		let position = abd.$planet_cc_poof$.$planet_getLocalPosition_poof$($planet_Float_poof$.$planet_ins_poof$.node, node);
		$planet_Float_poof$.$planet_ins_poof$.ui_pointer.node.setPosition(position);
		$planet_Float_poof$.$planet_ins_poof$.ui_pointer.node.active = true;

		// 手指引导的往复动画
		// tan A = 77/75;
		// distanceX = cos A * 80 = 56;
		// distanceY = sin A * 80 = 57;
		tween($planet_Float_poof$.$planet_ins_poof$.ui_pointer.node)
		.by(0.15, {position: v3(56, -57, 0)})
		.by(0.15, {position: v3(-56, 57, 0)})
		.union().repeat(3).delay(0.6)
		.union().repeatForever().start();
	}

	public static $planet_hidePointer_poof$(){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		if($planet_Float_poof$.$planet_ins_poof$.ui_pointer.node.active==false) return void 0;
		Tween.stopAllByTarget($planet_Float_poof$.$planet_ins_poof$.ui_pointer.node);
		$planet_Float_poof$.$planet_ins_poof$.ui_pointer.node.active = false;
	}

	public static $planet_showResetting_poof$(){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		$planet_Float_poof$.$planet_ins_poof$.$planet_node_resetting_poof$.active = true;

		Tween.stopAllByTarget($planet_Float_poof$.$planet_ins_poof$.$planet_op_resetting_poof$);
		tween($planet_Float_poof$.$planet_ins_poof$.$planet_op_resetting_poof$)
		.to(0.5, {opacity: 255}, {easing: 'quartOut'})
		.start();
	}

	public static $planet_hideResetting_poof$(){
		if(!$planet_Float_poof$.$planet_ins_poof$) return void 0;
		Tween.stopAllByTarget($planet_Float_poof$.$planet_ins_poof$.$planet_op_resetting_poof$);
		tween($planet_Float_poof$.$planet_ins_poof$.$planet_op_resetting_poof$)
		.to(0.5, {opacity: 0}, {easing: 'quartIn'})
		.call(()=>$planet_Float_poof$.$planet_ins_poof$.$planet_node_resetting_poof$.active = false)
		.start();
	}
}


